﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.Windows.Markup;
using System.ComponentModel;
using System.IO;

namespace Vision.Core.ActivityComponents.Conversion
{
	/// <summary>
	/// 
	/// </summary>
	/// <typeparam name="T"></typeparam>
	[ContentProperty("Body")]
	[System.ComponentModel.Designer(typeof(ToByteArrayDesigner))]
	public class ToByteArray<T> : NativeActivity
	{
		#region Declarations
		/// <summary>
		/// 
		/// </summary>
		[DefaultValue("")]
		[Category("Input")]
		public InArgument<T> Value { get; set; }

		/// <summary>
		/// 
		/// </summary>
		[Browsable(false)]
		[DefaultValue(null)]
		[DependsOn("Value")]
		public ActivityAction<byte[]> Body { get; set; }

		/// <summary>
		/// 
		/// </summary>
		[Category("Output")]
		public OutArgument<byte[]> Data { get; set; }
		#endregion

		public ToByteArray() : base()
		{
			this.Body = new ActivityAction<byte[]>()
			{
				Argument = new DelegateInArgument<byte[]>() { Name = "data" }
			};
		}

		#region Method(s)
		protected override void CacheMetadata(NativeActivityMetadata metadata)
		{
			RuntimeArgument valueArgument = new RuntimeArgument("Value", typeof(T), ArgumentDirection.In, true);
			metadata.Bind(this.Value, valueArgument);
			metadata.AddArgument(valueArgument);

			RuntimeArgument dataArgument = new RuntimeArgument("Data", typeof(byte[]), ArgumentDirection.Out);
			metadata.Bind(this.Data, dataArgument);
			metadata.AddArgument(dataArgument);
			metadata.AddDelegate(this.Body);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		protected override void Execute(NativeActivityContext context)
		{
			// creates the data
			parseData(context);
			if (this.Body != null)
			{
				context.ScheduleAction(this.Body, this.Data.Get(context), this.OnChildActivityCompleted);
			}
		}

		private void OnChildActivityCompleted(NativeActivityContext context, ActivityInstance completedInstance)
		{
			
		}

		private void parseData(NativeActivityContext context)
		{
			if (typeof(T) == typeof(string))
				parseStringData(context);
			else if (typeof(T) == typeof(Stream))
				parseStreamData(context);

		}

		/// <summary>
		/// Sets the data to a byte array from a string input.
		/// </summary>
		/// <param name="context"></param>
		private void parseStringData(NativeActivityContext context)
		{
			System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding();
			this.Data.Set(context, encoding.GetBytes(this.Value.Get<string>(context)));
		}

		/// <summary>
		/// Sets the data to a byte array from a stream input.
		/// </summary>
		/// <param name="context"></param>
		private void parseStreamData(NativeActivityContext context)
		{
			Stream dataStream = this.Value.Get<Stream>(context);

			byte[] total_stream = new byte[0];
			byte[] stream_array = new byte[0];

			byte[] buffer = new byte[1024];
			int read = 0;

			while ((read = dataStream.Read(buffer, 0, buffer.Length)) > 0)
			{
				stream_array = new byte[total_stream.Length + read];
				total_stream.CopyTo(stream_array, 0);
				Array.Copy(buffer, 0, stream_array, total_stream.Length, read);
				total_stream = stream_array;
			}

			this.Data.Set(context, total_stream);
		}
		#endregion
	}
}
